home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / DCLAP 6d / dclap6d / DBio / DSequence.cpp < prev    next >
Text File  |  1996-07-05  |  40KB  |  1,685 lines

  1. // DSequence.cp 
  2. // d.g.gilbert
  3.  
  4.  
  5.  
  6. #include "DSequence.h"
  7. #include "DSeqFile.h"
  8. #include "DSeqList.h"
  9. #include "DREnzyme.h"
  10. #include <ncbi.h>
  11. #include <dgg.h>
  12. #include <DUtil.h>
  13. #include <DFile.h>
  14. #include "ureadseq.h"
  15.  
  16.  
  17. char* DSequence::kConsensus = "Consensus";
  18. char  DSequence::indelHard = '-';
  19. char  DSequence::indelSoft = '~';
  20. char  DSequence::indelEdge = '.';
  21.  
  22.  
  23. Local char* gAminos        =    "ABCDEFGHIKLMNPQRSTVWXYZ*_.-~?";
  24. Local char* gIubbase    = "ACGTUMRWSYKVHDBXN_.-*~?";     //did include ".", for what?
  25. Local char* gPrimenuc    = "ACGTU_.-*~?";
  26. Local char* protonly    = "EFIPQZ";
  27. Local char* stdsymbols= "_.-*?";
  28. Local char* allsymbols= "_.-*?!=/**/[]()!&#$%^&=+;:/|`~'\"\\";
  29. Local char* seqsymbols= allsymbols;
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. // DSequence statics -----------------
  37.  
  38.  
  39. long DSequence::NucleicBits(char nuc)
  40. {
  41.     //char nuc= toupper(nuc);
  42.     switch (nuc) {
  43.         case 'a': case 'A': return kMaskA;  
  44.         case 'c': case 'C': return kMaskC;   
  45.         case 'g': case 'G': return kMaskG;   
  46.         case 't': case 'T': return kMaskT;   
  47.         case 'u': case 'U': return kMaskU;  // ==  ( kMaskT | kMaskExtra); 
  48.         case 'y': case 'Y': return (kMaskC | kMaskT);  
  49.         case 'k': case 'K': return (kMaskG | kMaskT);  
  50.         case 's': case 'S': return (kMaskG | kMaskC);  
  51.         case 'r': case 'R': return (kMaskG | kMaskA);  
  52.         case 'm': case 'M': return (kMaskA | kMaskC);  
  53.         case 'w': case 'W': return (kMaskA | kMaskT);  
  54.         case 'h': case 'H': return (kMaskA | kMaskC | kMaskT);  
  55.         case 'b': case 'B': return (kMaskG | kMaskC | kMaskT);  
  56.         case 'v': case 'V': return (kMaskG | kMaskC | kMaskA);  
  57.         case 'd': case 'D': return (kMaskG | kMaskT | kMaskA);  
  58.         case ' ': case '_': return 0;  //? spacers
  59.         case  0 : return 0;  
  60.         case 'n': case 'N': return kMaskNucs; 
  61.         default : 
  62.             {
  63.             if (nuc == indelHard || nuc == indelSoft)  return kMaskIndel;
  64.             else if (nuc == indelEdge) return 0; //return kMaskNucs; ???
  65.             else return 0; //kMaskNucs;  //?? match all or match none ??
  66.             }
  67.         }
  68. }
  69.  
  70.  
  71. Boolean DSequence::IsNucleicMatch( long xNucBits, long yNucBits)
  72. {
  73.         // note: Indel/spaces match nothing, including other indel/space ...
  74.     return 0 != ( (kMaskNucs & xNucBits) & (kMaskNucs & yNucBits));
  75. }
  76.  
  77.  
  78. char DSequence::NucleicConsensus( long xNucBits, long yNucBits)
  79.     char nuc; 
  80.     Boolean isrna, indel;
  81.  
  82.     if (xNucBits==0 || yNucBits==0) 
  83.         return ' ';  //?? either a space yields space ?
  84.     else {
  85.         indel= (kMaskIndel == xNucBits || kMaskIndel == yNucBits);
  86.         isrna= (kMaskU == xNucBits || kMaskU == yNucBits);
  87.         switch ( (kMaskNucs & xNucBits) | (kMaskNucs & yNucBits)) {
  88.             case kMaskA: nuc= 'A'; break;
  89.             case kMaskC: nuc= 'C'; break;
  90.             case kMaskG: nuc= 'G'; break;
  91.             case kMaskT: 
  92.                 if (isrna) nuc= 'U'; else nuc= 'T';
  93.                 break;
  94.                     //? do other ambig codes ?
  95.             default:    nuc= '.'; break; //? use this as Consensus other ?
  96.             }
  97.         if (indel) nuc= tolower(nuc); //?
  98.         }
  99.     return nuc;
  100. }
  101.  
  102.  
  103.  
  104. void DSequence::NucleicComplement( Boolean isrna, char* fromSeq, char* toSeq, long len)
  105. {
  106. // note: fromSeq may == toSeq 
  107.     register char b, c;
  108.     Boolean islow;
  109.      while (len--) {
  110.         b= *fromSeq++;
  111.         islow= islower(b);
  112.         if (islow) b= toupper(b);
  113.         switch (b) {
  114.             case 'C': c= 'G'; break;
  115.             case 'G': c= 'C'; break;
  116.             case 'A': if (isrna) c= 'U'; else c= 'T'; break;
  117.             case 'T':
  118.             case 'U': c= 'A'; break;
  119.             case 'R': c= 'Y'; break;
  120.             case 'Y': c= 'R'; break;
  121.             case 'M': c= 'K'; break;
  122.             case 'K': c= 'M'; break;
  123.             case 'S': c= 'S'; break;  // was mistaken 'w'
  124.             case 'W': c= 'W'; break;  // was mistaken 's'
  125.             case 'H': c= 'D'; break;
  126.             case 'D': c= 'H'; break;
  127.             case 'B': c= 'V'; break;
  128.             case 'V': c= 'B'; break;
  129.             default : c= b;   break;
  130.             }
  131.         if (islow) c= tolower(c);
  132.         *toSeq++= c;
  133.         }
  134. }
  135.  
  136.  
  137.  
  138. const char* DSequence::Amino123( char amino1)
  139. {
  140.  switch (toupper( amino1)) {
  141.      case 'A': return "Ala";
  142.      case 'M': return "Met";
  143.      case 'R': return "Arg";
  144.      case 'F': return "Phe";
  145.      case 'N': return "Asn";
  146.      case 'P': return "Pro";
  147.      case 'D': return "Asp";
  148.      case 'S': return "Ser";
  149.      case 'C': return "Cys";
  150.      case 'T': return "Thr";
  151.      case 'Q': return "Gln";
  152.      case 'W': return "Trp";
  153.      case 'E': return "Glu";
  154.      case 'Y': return "Tyr";
  155.      case 'G': return "Gly";
  156.      case 'V': return "Val";
  157.      case 'H': return "His";
  158.      case 'I': return "Ile";
  159.      case 'B': return "Asx";
  160.      case 'L': return "Leu";
  161.      case 'Z': return "Glx";
  162.      case 'K': return "Lys";
  163.      case 'X': return "Xaa";
  164.      case '*': return "End";
  165.      case ' ': return "   ";
  166.      default : return "???"; //??
  167.      }
  168. }
  169.  
  170.  
  171. char DSequence::Amino321( char* amino)
  172. {
  173.     char    aa[4];
  174.     aa[0]= toupper(amino[0]);
  175.     aa[1]= tolower(amino[1]);
  176.     aa[2]= tolower(amino[2]);
  177.     aa[3]= 0;
  178.     
  179.              if (!StrCmp(aa,"Ala")) return 'A';
  180.     else if (!StrCmp(aa,"Met")) return 'M';
  181.     else if (!StrCmp(aa,"Arg")) return 'R';         
  182.     else if (!StrCmp(aa,"Phe")) return 'F';
  183.     else if (!StrCmp(aa,"Asn")) return 'N';       
  184.     else if (!StrCmp(aa,"Pro")) return 'P';
  185.     else if (!StrCmp(aa,"Asp")) return 'D';    
  186.     else if (!StrCmp(aa,"Ser")) return 'S';
  187.     else if (!StrCmp(aa,"Cys")) return 'C';         
  188.     else if (!StrCmp(aa,"Thr")) return 'T';
  189.     else if (!StrCmp(aa,"Gln")) return 'Q';       
  190.     else if (!StrCmp(aa,"Trp")) return 'W';
  191.     else if (!StrCmp(aa,"Glu")) return 'E';    
  192.     else if (!StrCmp(aa,"Tyr")) return 'Y';
  193.     else if (!StrCmp(aa,"Gly")) return 'G';          
  194.     else if (!StrCmp(aa,"Val")) return 'V';
  195.     else if (!StrCmp(aa,"His")) return 'H';
  196.     else if (!StrCmp(aa,"Ile")) return 'I';       
  197.     else if (!StrCmp(aa,"Asx")) return 'B';
  198.     else if (!StrCmp(aa,"Leu")) return 'L';          
  199.     else if (!StrCmp(aa,"Glx")) return 'Z';
  200.     else if (!StrCmp(aa,"Lys")) return 'K';           
  201.     else if (!StrCmp(aa,"End")) return '*';           
  202.     else if (!StrCmp(aa,"   ")) return ' '; //??           
  203.     else return 'X';
  204. }
  205.  
  206.  
  207. char* DSequence::Nucleic23Protein( char* nucs, long nbases)
  208. //!! Need to do this w/ NucBits so ambiguity codes work !!
  209. //!! The CodonTable.codon == acodon should be IsNucleicMatch( bits(codon), bits(acodon)) 
  210. {
  211.     long    i;  //borland 16bit don't like longs for iterators !?
  212.     char  *ap, *kp, *aminos;
  213.  
  214.     if (DCodons::NotAvailable()) return NULL; // (gCodonTable[0].amino == 0)
  215.  
  216.     aminos= StrDup( nucs);
  217.     for (i= 0, ap= aminos; i<nbases; i++) {
  218.         register char c= toupper( *ap);
  219.         if (c=='U') c= 'T';
  220.         *ap++= c;
  221.         }
  222.  
  223.     for (i= 0, ap= aminos, kp= aminos; i<nbases; i++) {
  224.         for (long j=0; j<64; j++)
  225.             if ( MemCmp(DCodons::codon(j), ap, 3) == 0) { //gCodonTable[j].codon
  226.                 *kp++= DCodons::amino(j); // gCodonTable[j].amino;
  227.                 break;
  228.                 }
  229.         }
  230.     *kp= '\0';
  231.     aminos= (char*) MemMore( aminos, kp - aminos + 1);
  232.     return aminos;
  233.  
  234.  
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241.  
  242. // DSequence -----------------
  243.  
  244.  
  245. DSequence::DSequence()
  246. {
  247.     fBases= (char*) MemGet(1,true); 
  248.   fMasks= NULL; //(char*) MemGet(1,true); 
  249.   fMasksOk= false;
  250.     fInfo    = (char*) MemGet(1,true);     
  251.     fName = StrDup("Untitled");         //!? need unique name, eg. Noname-1,noname-2...
  252.     fKind = kOtherSeq;         //? user default
  253.     fLength        = 0;
  254.     fChecksum    = 0;
  255.     fIndex        = 0; //dummy
  256.     fModTime    = gUtil->time();
  257.     fChanged    = FALSE; //TRUE;
  258.     fIsMega        = FALSE;
  259.     fShowORF    = FALSE;
  260.     fShowRE        = FALSE;
  261.     fShowTrace = FALSE;
  262.  
  263.     fDeleted    = FALSE; 
  264.     fOpen            = FALSE;
  265.     fSearchRec.targ= NULL;
  266.     fOrigin    = 0;
  267.     fSelStart= 0;
  268.     fSelBases= 0;
  269. }
  270.  
  271.  
  272. DSequence::~DSequence()  
  273. {
  274.     MemFree(fBases);
  275.     MemFree(fMasks);
  276.     MemFree(fInfo);
  277.     MemFree(fName);
  278.     MemFree(fSearchRec.targ);
  279. }
  280.  
  281.  
  282. DObject* DSequence::Clone() // override 
  283. {    
  284.     DSequence* aSeq= (DSequence*) DObject::Clone();
  285.     aSeq->fBases= NULL; aSeq->SetBases( fBases, true);  
  286.     aSeq->fMasks= NULL; aSeq->SetMasks( fMasks, true); 
  287.     aSeq->fInfo=  StrDup( fInfo);
  288.     aSeq->fName=  StrDup( fName);
  289.     aSeq->fSearchRec.targ= StrDup( fSearchRec.targ);
  290.     return aSeq;
  291. }
  292.  
  293. void DSequence::CopyContents( DSequence* fromSeq)
  294. {
  295.     SetBases( fromSeq->fBases, true); 
  296.     SetMasks( fromSeq->fMasks, true); 
  297.     SetInfo( fromSeq->fInfo); 
  298.     SetName( fromSeq->fName); 
  299.     fKind            = fromSeq->fKind;          
  300.     fLength        = fromSeq->fLength;
  301.     fChecksum    = fromSeq->fChecksum;
  302.     fModTime    = fromSeq->fModTime;
  303.     fChanged    = fromSeq->fChanged;
  304.     fDeleted    = fromSeq->fDeleted; 
  305.     fOpen            = fromSeq->fOpen;
  306.     fIndex        = fromSeq->fIndex;
  307.     fSearchRec= fromSeq->fSearchRec;
  308.     fSearchRec.targ= StrDup( fromSeq->fSearchRec.targ);
  309. }
  310.  
  311. void DSequence::SetBases( char*& theBases, Boolean duplicate)
  312. {
  313.     long  newlen= (theBases) ? StrLen(theBases) : 0;
  314.     if (fBases) { 
  315.         if (fLength>0 && 
  316.             (fLength != newlen || MemCmp( theBases, fBases, newlen)!= 0))
  317.                 fChanged= TRUE;
  318.         MemFree(fBases); 
  319.         fBases= NULL; fLength= 0; 
  320.         }
  321.     if (theBases) {
  322.         if (duplicate) fBases = StrDup(theBases); 
  323.         else { fBases= theBases; theBases= NULL; }
  324.         fLength= newlen;  
  325.         }
  326.     fModTime= gUtil->time();
  327.     fMasksOk= false; // assume SetBases always called before SetMask...
  328. }
  329.  
  330.  
  331. void DSequence::UpdateBases( char* theBases, long theLength)
  332. {
  333.     fBases =  theBases;  
  334.     fLength= theLength;
  335.     fMasksOk= false; // assume this allways called before SetMask...
  336. }
  337.  
  338.  
  339. void DSequence::SetMasks( char*& theMasks, Boolean duplicate)
  340. {
  341.     if (fMasks) MemFree(fMasks);
  342.     if (theMasks) {
  343.         if (duplicate) fMasks = StrDup(theMasks);  
  344.         else { fMasks= theMasks; theMasks= NULL; }
  345.         FixMasks();
  346.         }
  347.     else {
  348.         fMasks= NULL;
  349.         fMasksOk= false;
  350.         }
  351. }
  352.  
  353. void DSequence::FixMasks()
  354. {
  355.     ulong i, mlen= 0;
  356.     if (!fMasks) { 
  357.         mlen= 1+fLength;
  358.         fMasks= (char*) MemGet(mlen,true);  
  359.         for (i=0; i<mlen; i++) fMasks[i] |= 0x80; // set high bit so Strxxx sees it as non-null
  360.         fMasks[mlen-1]= 0;
  361.         }
  362.     else { 
  363.         mlen= 1+StrLen(fMasks);
  364.         if (fLength+1 != mlen) {
  365.             fMasks= (char*) Nlm_MemExtend( fMasks, fLength+1, mlen);
  366.             mlen= fLength+1; 
  367.             for (i=0; i<mlen; i++) fMasks[i] |= 0x80; 
  368.             fMasks[mlen-1]= 0;
  369.             } 
  370.         }
  371.     fMasksOk= true;
  372. }
  373.  
  374. short DSequence::MaskAt(long baseindex, short masklevel)
  375. {
  376.     short b = kMaskEmpty;
  377.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength) {
  378.         b= (unsigned char) fMasks[baseindex];
  379.         switch (masklevel) {
  380.             case 0: b &= 0x7f; break; // return full mask - top (0x80) bit
  381.             case 1: b &= 1;  break;  
  382.             case 2: b &= 2;  break;
  383.             case 3: b &= 4;  break;
  384.             case 4: b &= 8;  break;
  385.                 // 5-7 reserved for now
  386.             case 5: b &= 16;  break;
  387.             case 6: b &= 32;  break;
  388.             case 7: b &= 64;  break;
  389.             default: b = kMaskEmpty; break;
  390.             }
  391.         }
  392.     return b;
  393. }
  394.  
  395. Boolean DSequence::IsMasked(unsigned char maskbyte, short masklevel)
  396. {
  397.     short b= (unsigned char) maskbyte;
  398.     switch (masklevel) {
  399.         case 0: b &= 0x7f; break; // return full mask - top (0x80) bit
  400.         case 1: b &= 1;  break;  
  401.         case 2: b &= 2;  break;
  402.         case 3: b &= 4;  break;
  403.         case 4: b &= 8;  break;
  404.                 // 5-7 reserved for now
  405.         case 5: b &= 16;  break;
  406.         case 6: b &= 32;  break;
  407.         case 7: b &= 64;  break;
  408.         default: b = kMaskEmpty; break;
  409.         }
  410.     return (b > 0);
  411. }
  412.  
  413.  
  414. inline void SetMaskByte( char& b, short masklevel, short maskval)
  415. {
  416.     switch (masklevel) {
  417.         case 1: if (maskval) b |= 1; else b &= ~1; break;
  418.         case 2: if (maskval) b |= 2; else b &= ~2; break;
  419.         case 3: if (maskval) b |= 4; else b &= ~4; break;
  420.         case 4: if (maskval) b |= 8; else b &= ~8; break;
  421.             // reserve bits 5, 6, 7 & 8 for now 
  422.         case 5: if (maskval) b |= 16; else b &= ~16; break;
  423.         case 6: if (maskval) b |= 32; else b &= ~32; break;
  424.         case 7: if (maskval) b |= 64; else b &= ~64; break;
  425.         // -- 7 & 8 may go unused to store data in printchar form
  426.         default: break;
  427.         }
  428.     //if (b) masklevel--; // debugging b val
  429. }
  430.  
  431. void DSequence::SetMaskAt(long baseindex, short masklevel, short maskval)
  432. {
  433.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  434.         ::SetMaskByte(fMasks[baseindex],masklevel, maskval);
  435. }
  436.  
  437.  
  438. void DSequence::SetMask(short masklevel, short maskval)
  439. {
  440.     long  baseindex;
  441.     if (fMasks && fMasksOk) 
  442.      for (baseindex=0; baseindex<fLength; baseindex++) 
  443.         ::SetMaskByte(fMasks[baseindex], masklevel, maskval);
  444. }
  445.  
  446.  
  447. inline void FlipMaskByte( char& b, short masklevel)
  448. {
  449.     switch (masklevel) {
  450.         case 1: b ^= 1;  break;  
  451.         case 2: b ^= 2;  break;
  452.         case 3: b ^= 4;  break;
  453.         case 4: b ^= 8;  break;
  454.                 // 5-7 reserved for now?
  455.         case 5: b ^= 16;  break;
  456.         case 6: b ^= 32;  break;
  457.         case 7: b ^= 64;  break;
  458.         default:  break;
  459.         }
  460.     //if (b) masklevel--; // debugging b val
  461. }
  462.  
  463. void DSequence::FlipMaskAt(long baseindex, short masklevel)
  464. {
  465.     if (fMasks && fMasksOk && baseindex>=0 && baseindex<fLength)  
  466.         ::FlipMaskByte(fMasks[baseindex],masklevel);
  467. }
  468.  
  469. void DSequence::FlipMask(short masklevel)
  470. {
  471.     long  baseindex;
  472.     if (fMasks && fMasksOk) 
  473.      for (baseindex=0; baseindex<fLength; baseindex++)  
  474.         FlipMaskByte(fMasks[baseindex],masklevel);
  475. }
  476.  
  477.  
  478. void DSequence::SetInfo( char* theInfo)
  479. {
  480.     if (fInfo) MemFree(fInfo);
  481.     fInfo = StrDup(theInfo);  
  482. }
  483.  
  484. void DSequence::SetName( char* theName)
  485. {
  486.     if (fName) MemFree(fName);
  487.     fName = StrDup(theName);  
  488. }
  489.  
  490. void DSequence::SetKind( short theKind)
  491. {
  492.     fKind= theKind;  
  493. }
  494.  
  495. void DSequence::SetIndex( short theIndex)
  496. {
  497.     fIndex= theIndex;  
  498. }
  499.  
  500. char* DSequence::KindStr() const 
  501. {
  502.     switch (fKind) {
  503.         case kDNA             : return "DNA";
  504.         case kRNA             : return "RNA";
  505.         case kNucleic   : return "Nucleic";
  506.         case kAmino         : return "Protein";
  507.         default                    :
  508.         case kOtherSeq  : return "Unknown";
  509.         }
  510. }
  511.  
  512.  
  513. void DSequence::SetTime( unsigned long theTime)
  514. {
  515.     fModTime= theTime;
  516. }
  517.  
  518. void DSequence::SetOrigin( long theOrigin)
  519. {
  520.     fOrigin= theOrigin;
  521. }
  522.  
  523. void DSequence::Modified()  
  524. {
  525.     fModTime    = gUtil->time();
  526.     fChanged    = TRUE;
  527. }
  528.  
  529. void DSequence::Reformat(short format)
  530. {
  531.     // later...? 
  532. }
  533.  
  534. void DSequence::UpdateFlds()
  535. {
  536.     long         seqlen;
  537.     short     kind;
  538.     unsigned long check;
  539.     fLength= StrLen(fBases);
  540.     GetSeqStats(fBases, fLength, &kind, &check, &seqlen);
  541.     //fValidLength= seqlen; //?? is fLength == StrLen(fBases) or is it <= that, only valid bases??
  542.     fKind            = kind;
  543.     fChecksum    = check;
  544.     //fChanged    = FALSE;
  545. }
  546.  
  547.  
  548.  
  549.  
  550.  
  551. void DSequence::SetSelection( long start, long nbases)
  552. {
  553.     fSelStart= start;
  554.     fSelBases= nbases;
  555. }
  556.  
  557. void DSequence::ClearSelection()
  558. {
  559.     fSelStart= 0;
  560.     fSelBases= 0;
  561. }
  562.  
  563. void    DSequence::GetSelection( long& start, long& nbases)
  564. {
  565.     if (fSelBases==0) {
  566.         start= 0;
  567.         nbases= fLength;
  568.         }    
  569.     else if (fLength>0) {
  570.         start= fSelStart;
  571.         nbases= Min( fSelBases, fLength - fSelStart);
  572.         }    
  573.     else {
  574.         start= 0;
  575.         nbases= 0;
  576.         }
  577. }
  578.  
  579.  
  580. DSequence* DSequence::CopyRange()
  581. {  
  582.             //note: start == 0 == 1st position 
  583.     DSequence* aSeq= (DSequence*) Clone();
  584.     if (fSelStart > 0 || fSelBases > 0) {
  585.         char* h= aSeq->fBases;
  586.         char* m= aSeq->fMasks;
  587.         Boolean domask= (fMasks && fMasksOk);
  588.  
  589.         long len= aSeq->fLength;
  590.         if (fSelStart > 0) {
  591.             len -= fSelStart;
  592.             MemMove( h, h + fSelStart, len);
  593.             if (domask) MemMove( m, m + fSelStart, len);
  594.             }
  595.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  596.         h= (char*) MemMore( h, len+1);
  597.         h[len]= '\0'; //((char*)h+len) = '\0';
  598.         aSeq->fBases= h;
  599.         if (domask) {
  600.             m= (char*) MemMore( m, len+1);
  601.             m[len]= '\0';    
  602.             aSeq->fMasks= m;
  603.             }
  604.         }
  605.     aSeq->UpdateFlds();
  606.     aSeq->Modified();
  607.     return aSeq;
  608. }
  609.  
  610.  
  611. DSequence* DSequence::CutRange()
  612. {
  613. /* aSeq.Cutrange means:  
  614.         (a) selected range (fSelStart..fSelStart+fSelBases) is copied into Result; &&
  615.         (b) selected range is removed from this
  616. */
  617.  
  618.     DSequence* aSeq= CopyRange();
  619.     if (fSelStart > 0 || fSelBases > 0) {
  620.         if (fSelStart<0) fSelStart= 0;
  621.         char* h= this->fBases;
  622.         char* m= this->fMasks;
  623.         Boolean domask= (fMasks && fMasksOk);
  624.         long len= this->fLength;
  625.         long top= len - fSelStart - fSelBases;
  626.         if (fSelBases > 0 && fSelBases < len) {
  627.             MemMove( h+fSelStart, h+fSelStart+fSelBases, top);
  628.             if (domask) MemMove( m+fSelStart, m+fSelStart+fSelBases, top);
  629.             }
  630.         len= fSelStart + top;
  631.         h= (char*) MemMore( h, len+1);
  632.         *((char*)h+len)= '\0';       //h[len]= '\0';
  633.         this->fBases= h;
  634.         if (domask) {
  635.             m= (char*) MemMore( m, len+1);
  636.             *((char*)m+len)= '\0';    
  637.             this->fMasks= m;
  638.             }
  639.         }
  640.     UpdateFlds();    
  641.     Modified();
  642.     return aSeq;
  643. }
  644.  
  645. void DSequence::InsertSpacers( long insertPoint, long insertCount, char spacer)
  646.     long i;
  647.     char *cp;
  648.     char* h= this->fBases;
  649.     char* m= this->fMasks;
  650.     Boolean domask= (fMasks && fMasksOk);
  651.     long len= this->fLength;
  652.     if (insertPoint<0) insertPoint= 0;
  653.     else if (insertPoint>len-1) insertPoint= len-1;
  654.     h= (char*) MemMore( h, len+insertCount+1);
  655.     cp = h+insertPoint;
  656.     MemMove( cp+insertCount, cp, len-insertPoint);
  657.     for ( i= 0; i<insertCount; i++)  *cp++= spacer;
  658.     h[len+insertCount]= '\0';
  659.     this->fBases= h;
  660.     if (domask) {
  661.         m= (char*) MemMore( m, len+insertCount+1);
  662.         cp = m+insertPoint;
  663.         char cmask= *cp;
  664.         MemMove( cp+insertCount, cp, len-insertPoint);
  665.         for ( i= 0; i<insertCount; i++)  *cp++= cmask;
  666.         m[len+insertCount]= '\0';
  667.         this->fMasks= m;
  668.         }
  669.     this->UpdateFlds();    
  670.     this->Modified();
  671. }
  672.  
  673.  
  674. DSequence* DSequence::PasteBases( long insertPoint, char* fromBases, char* fromMasks)
  675.     long add;
  676.     DSequence* aSeq= (DSequence*) Clone();
  677.     if (fromBases) add= StrLen( fromBases);  else add= 0;
  678.     if (add>0) {
  679.         char* h= aSeq->fBases;
  680.         char* m= aSeq->fMasks;
  681.         Boolean domask= (fMasks && fMasksOk);
  682.         long len = aSeq->fLength;
  683.         if (insertPoint<=0) {
  684.             fromBases= StrDup( fromBases);
  685.             StrExtendCat( &fromBases, h);
  686.             MemFree( h);
  687.             h= fromBases;
  688.             if (domask && fromMasks) {
  689.                 fromMasks= StrDup( fromMasks);
  690.                 StrExtendCat( &fromMasks, m);
  691.                 MemFree( m);
  692.                 m= fromMasks;
  693.                 }
  694.             }        
  695.         else if (insertPoint>=len) { 
  696.             StrExtendCat( &h, fromBases);
  697.             if (domask) StrExtendCat( &m, fromMasks);
  698.             }
  699.         else { 
  700.             h= (char*) MemMore( h, len+add);
  701.             MemMove( h+insertPoint+add, h+insertPoint, len-insertPoint);
  702.             MemMove( h+insertPoint+add, fromBases, add);
  703.             *((char*)h+len+add)= '\0';
  704.             if (domask) {
  705.                 m= (char*) MemMore( m, len+add);
  706.                 MemMove( m+insertPoint+add, m+insertPoint, len-insertPoint);
  707.                 MemMove( m+insertPoint+add, fromMasks, add);
  708.                 *((char*)m+len+add)= '\0';
  709.                 }
  710.             }
  711.         aSeq->fBases= h;
  712.         aSeq->fMasks= m;
  713.         }
  714.     aSeq->UpdateFlds();    
  715.     aSeq->Modified();
  716.     return aSeq;
  717. }
  718.  
  719.  
  720. DSequence* DSequence::Reverse()
  721. {
  722.     long i;
  723.     DSequence* aSeq= (DSequence*) Clone();    
  724.     if (fSelStart < 0) fSelStart= 0;
  725.     long len= aSeq->fLength - fSelStart;
  726.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  727.     char* pc= this->fBases+fSelStart + len;
  728.     char* pr= aSeq->fBases+fSelStart;
  729.     for (i= 0; i<len; i++) *pr++= *--pc;
  730.     Boolean domask= (fMasks && fMasksOk);
  731.     if (domask) {
  732.         pc= this->fMasks+fSelStart + len;
  733.         pr= aSeq->fMasks+fSelStart;
  734.         for (i= 0; i<len; i++) *pr++= *--pc;
  735.         }
  736.     aSeq->UpdateFlds();
  737.     aSeq->Modified();
  738.     return aSeq;
  739. }
  740.  
  741.  
  742. DSequence* DSequence::Complement()
  743. // A->T, T->A, G->C, C->G  
  744. {
  745.     Boolean        isrna;
  746.     DSequence* aSeq= (DSequence*) Clone();    
  747.     
  748.     if (fKind == kRNA) isrna= TRUE;
  749.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  750.     else return aSeq;    
  751.         
  752.     if (fSelStart < 0) fSelStart= 0;
  753.     long len= aSeq->fLength - fSelStart;
  754.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  755.     char* pc= this->fBases+fSelStart;
  756.     char* pr= aSeq->fBases+fSelStart;
  757.     NucleicComplement( isrna, pc, pr, len);
  758.         
  759.     aSeq->UpdateFlds();
  760.     aSeq->Modified();
  761.     return aSeq;
  762. }
  763.  
  764.  
  765.  
  766. DSequence* DSequence::ChangeCase(Boolean toUpper)
  767. // g->G or G->g
  768. {
  769.     DSequence* aSeq= (DSequence*) Clone();    
  770.     
  771.     if (fSelStart < 0) fSelStart= 0;
  772.     char* h= aSeq->fBases;
  773.     long len= aSeq->fLength - fSelStart;
  774.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  775.     char* pc= this->fBases+fSelStart;
  776.     char* pr= aSeq->fBases+fSelStart;
  777.     
  778.     long i;
  779.     if (toUpper) for (i= 0; i<len; i++) {
  780.         *pr++= toupper(*pc); pc++;
  781.         }
  782.     else for (i= 0; i<len; i++) {
  783.         *pr++= tolower(*pc); pc++;
  784.         }    
  785.         
  786.     aSeq->UpdateFlds();
  787.     aSeq->Modified();
  788.     return aSeq;
  789. }
  790.  
  791. DSequence* DSequence::Dna2Rna(Boolean toRna)
  792. // T->U or U->T 
  793. {
  794.     Boolean        isrna;
  795.     DSequence* aSeq= (DSequence*) Clone();    
  796.     
  797.     if (fKind==kRNA) isrna= TRUE;
  798.     else if (fKind == kDNA || fKind == kNucleic) isrna= FALSE;
  799.     else return aSeq;    
  800.      
  801.     if (fSelStart < 0) fSelStart= 0;
  802.     long len= aSeq->fLength - fSelStart;
  803.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  804.     char* pc= this->fBases+fSelStart;
  805.     char* pr= aSeq->fBases+fSelStart;
  806.     
  807.     long i;
  808.     char b, c;
  809.     if (toRna) for (i= 0; i<len; i++) {
  810.         b= *pc++;
  811.         if (b=='T') c= 'U';
  812.         else if (b=='t') c= 'u';
  813.         else c= b;
  814.         *pr++= c;
  815.         }
  816.     else for (i= 0; i<len; i++) {
  817.         b= *pc++;
  818.         if (b=='U') c= 'T';
  819.         else if (b=='u') c= 't';
  820.         else c= b;
  821.         *pr++= c;
  822.         }    
  823.         
  824.     aSeq->UpdateFlds();
  825.     aSeq->Modified();
  826.     return aSeq;
  827. }
  828.  
  829.  
  830. DSequence* DSequence::LockIndels( Boolean doLock)
  831. // indelSoft -> indelHard or vice versa 
  832. {    
  833.     char b, c, fromc, toc;
  834.     DSequence* aSeq= (DSequence*) Clone();    
  835.     
  836.     if (fSelStart < 0) fSelStart= 0;
  837.     long  len= aSeq->fLength - fSelStart;
  838.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  839.     char* pc= this->fBases+fSelStart;
  840.     char* pr= aSeq->fBases+fSelStart;
  841.     
  842.     if (doLock) { fromc= indelSoft; toc= indelHard; }
  843.     else { fromc= indelHard; toc= indelSoft; }
  844.     
  845.     for (long i= 0; i<len; i++) {
  846.         b= *pc++;
  847.         if (b == fromc) c= toc;
  848.         else c= b;
  849.         *pr++= c;
  850.         }    
  851.         
  852.     aSeq->UpdateFlds();
  853.     aSeq->Modified();
  854.     return aSeq;
  855. }
  856.  
  857.  
  858. DSequence* DSequence::Slide( long slideDist)
  859. /* insert "-" below (+dist) or above (-dist) of seq range,
  860.     squeeze out "-" above (below) of range
  861. */
  862. {     
  863.     long         slideSave, newlen, fulllen, len, i, j= 0;
  864.     char         b, cutchar, cutmask;
  865.     char        *pc, *pr;
  866.     
  867.     DSequence* aSeq= (DSequence*) Clone();    
  868.     if (fSelStart < 0) fSelStart= 0;
  869.     fulllen= aSeq->fLength;
  870.     len= fulllen - fSelStart;
  871.     Boolean domask= (fMasks && fMasksOk);
  872.     Boolean dosqueeze= true; //(indelSoft & 0x80 != 0); // quick fix flag
  873.     indelSoft &= 0x7f;
  874.     
  875.     if (slideDist < 0) {
  876.         // tough... do if below works...
  877.         // really need ability to extend seq in 5' (lower) direction 
  878.         //! build pr in reverse, then flip it....
  879.  
  880.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  881.         slideDist= -slideDist;
  882.         slideSave= slideDist;
  883.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fulllen+slideDist);
  884.         pr= aSeq->fBases;
  885.         pc= this->fBases + fulllen;
  886.         for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  887.              
  888.         if (pr == aSeq->fBases || *(pr-1) == indelEdge) cutchar= indelEdge;
  889.         else cutchar= indelSoft; //??
  890.         for (i=0; i<slideDist; i++) *pr++= cutchar;
  891.  
  892.         pc= this->fBases+fSelStart+len;
  893.         for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  894.             
  895.         pc= this->fBases+fSelStart;
  896.         for (i= fSelStart-1; i>=0; i--) {
  897.             b= *--pc;
  898.             if (dosqueeze && slideDist>0 && (b==indelSoft || b==indelEdge)) slideDist--;
  899.             else {
  900.                 *pr++= b;
  901.                 }
  902.             }
  903.  
  904.         newlen= pr - aSeq->fBases;
  905.         char* htmp= (char*) MemNew(newlen+1);
  906.         pc= htmp;
  907.         for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  908.         pc= '\0';
  909.         MemFree(aSeq->fBases);
  910.         aSeq->fBases = htmp;  
  911.         aSeq->fLength= newlen;
  912.         aSeq->fOrigin= fulllen - newlen; //== this->fLength - aSeq->fLength
  913.  
  914.         if (domask) {
  915.             slideDist= slideSave;
  916.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fulllen+slideDist);
  917.             pr= aSeq->fMasks;
  918.             pc= this->fMasks + fulllen;
  919.             for (i= fulllen-1; i >= fSelStart+len; i--) *pr++= *--pc;
  920.                  
  921.             cutmask= 0x80; // required empty mask  
  922.             for (i=0; i<slideDist; i++) *pr++= cutmask;
  923.     
  924.             pc= this->fMasks+fSelStart+len;
  925. #ifdef WIN_MSWIN
  926.             // mswin is crashing here for no obvious reason
  927.             //pc--; len--;
  928.             for (i= fSelStart + len - 1; i >= fSelStart; i--) {
  929.                  register short amask;
  930.                  --pc;
  931.                  amask= *pc;    //mswin bomb is here !
  932.                  *pr= amask;
  933.                  pr++;
  934.          }
  935. #else
  936.             for (i= fSelStart+len-1; i >= fSelStart; i--) *pr++= *--pc;
  937. #endif
  938.             pc= this->fMasks+fSelStart;
  939.             for (i= fSelStart-1; i>=0; i--) {
  940.                 b= *--pc;
  941.                 if (slideDist>0 && (b==cutmask)) slideDist--;
  942.                 else {
  943.                     *pr++= b;
  944.                     }
  945.                 }
  946.                 
  947.             newlen= pr - aSeq->fMasks;
  948.             htmp= (char*) MemNew(newlen+1);
  949.             pc= htmp;
  950.             for (i=0; i<newlen; i++) *pc++= *--pr; //pr[j-i+1];
  951.             pc= '\0';
  952.             MemFree(aSeq->fMasks);
  953.             aSeq->fMasks = htmp;  
  954.             }
  955.             
  956.         }    
  957.         
  958.     else if (slideDist > 0) {
  959.         fulllen= len;
  960.         if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  961.         aSeq->fBases= (char*) MemMore(aSeq->fBases, 2+fSelStart+fulllen+slideDist); //make it large enough
  962.  
  963.         pr= aSeq->fBases;
  964.       if (fSelStart==0 || pr[fSelStart-1]==indelEdge) cutchar= indelEdge; 
  965.         else cutchar= indelSoft; 
  966.  
  967.         pc= this->fBases+fSelStart;
  968.         pr= aSeq->fBases+fSelStart;
  969.  
  970.         for (j= 0; j<slideDist; j++) *pr++= cutchar;
  971.         for (i= 0; i<len; i++) *pr++= *pc++; 
  972.     
  973.         for (i= len; i<fulllen; i++) {
  974.             b= *pc++;
  975.             if (dosqueeze && slideDist>0 && (b==indelSoft || b==indelEdge)) 
  976.                 slideDist--;
  977.             else {
  978.                 *pr++= b;
  979.                 }
  980.             }
  981.         
  982.         *pr= 0;
  983.         newlen= pr - aSeq->fBases; 
  984.         aSeq->fBases= (char*)MemMore(aSeq->fBases, newlen+1);  
  985.         
  986.         if (domask) {
  987.             aSeq->fMasks= (char*) MemMore(aSeq->fMasks, 2+fSelStart+fulllen+slideDist);
  988.           cutmask= 0x80; 
  989.             pc= this->fMasks+fSelStart;
  990.             pr= aSeq->fMasks+fSelStart;
  991.     
  992.             for (j= 0; j<slideDist; j++) *pr++= cutmask;
  993.             for (i= 0; i<len; i++) *pr++= *pc++; 
  994.  
  995.             for (i= len; i<fulllen; i++) {
  996.                 b= *pc++;
  997.                 if (slideDist>0 && (b==cutmask)) // this is BAD? must be done w/ base slide !?
  998.                     slideDist--;
  999.                 else {
  1000.                     *pr++= b;
  1001.                     }
  1002.                 }
  1003.             
  1004.             *pr= 0;
  1005.             newlen= pr - aSeq->fMasks; 
  1006.             aSeq->fMasks= (char*)MemMore(aSeq->fMasks, newlen+1);  
  1007.             }
  1008.         }
  1009.             
  1010.     aSeq->UpdateFlds();
  1011.     aSeq->Modified();
  1012.     return aSeq;
  1013. }
  1014.  
  1015.  
  1016. DSequence* DSequence::Compress()
  1017. // pull out "-", ".", ? anything but nuc/aa codes ? 
  1018. {
  1019.     long  len, fulllen, i;
  1020.     char     b, c;
  1021.     char * mc, * mr;
  1022.     Boolean domask= (fMasks && fMasksOk);
  1023.  
  1024.     DSequence* aSeq= (DSequence*) Clone();    
  1025.     if (fSelStart < 0) fSelStart= 0;
  1026.     len= aSeq->fLength - fSelStart;
  1027.     fulllen= len;
  1028.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  1029.     char* pc= this->fBases+fSelStart;
  1030.     char* pr= aSeq->fBases+fSelStart;
  1031.     if (domask) {
  1032.         mc= this->fMasks+fSelStart;
  1033.         mr= aSeq->fMasks+fSelStart;
  1034.         }
  1035.         
  1036.     if (domask) for (i= 0; i<len; i++) {
  1037.         b= *pc++;
  1038.         c= *mc++;
  1039.         if (b!=indelSoft && b!=indelEdge) { 
  1040.             *pr++= b;
  1041.             *mr++= c;
  1042.             }
  1043.         }
  1044.     else for (i= 0; i<len; i++) {
  1045.         b= *pc++;
  1046.         if (b!=indelSoft && b!=indelEdge) 
  1047.             *pr++= b;
  1048.         }
  1049.     for (i=len; i<fulllen; i++) *pr++= *pc++;
  1050.     if (domask) for (i=len; i<fulllen; i++) *mr++= *mc++;
  1051.  
  1052.     long newlen= pr - aSeq->fBases;
  1053.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen+1);
  1054.     aSeq->fBases[newlen]= 0;
  1055.     if (domask) {
  1056.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen+1);
  1057.         aSeq->fMasks[newlen]= 0;
  1058.         }
  1059.         
  1060.     aSeq->UpdateFlds();
  1061.     aSeq->Modified();
  1062.     return aSeq;
  1063. }
  1064.  
  1065.  
  1066.  
  1067.  
  1068. DSequence* DSequence::CompressFromMask(short masklevel)
  1069. {
  1070.     long  len, fulllen, i;
  1071.     char     b, c;
  1072.     char * mc, * mr;
  1073.     Boolean domask= (fMasks && fMasksOk && masklevel>0);
  1074.  
  1075.     if (!domask) return NULL; // or aSeq ???
  1076.     DSequence* aSeq= (DSequence*) Clone();    
  1077.     //if (!domask) return aSeq;  
  1078.  
  1079.     if (fSelStart < 0) fSelStart= 0;
  1080.     len= aSeq->fLength - fSelStart;
  1081.     fulllen= len;
  1082.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  1083.     char* pc= this->fBases+fSelStart;
  1084.     char* pr= aSeq->fBases+fSelStart;
  1085.     mc= this->fMasks+fSelStart;
  1086.     mr= aSeq->fMasks+fSelStart;
  1087.          
  1088.     for (i= 0; i<len; i++) {
  1089.         b= *pc++;
  1090.         c= *mc++;
  1091.         if (IsMasked(c, masklevel)) { 
  1092.             *pr++= b;
  1093.             *mr++= c;
  1094.             }
  1095.         }
  1096.     for (i=len; i<fulllen; i++) *pr++= *pc++;
  1097.     for (i=len; i<fulllen; i++) *mr++= *mc++;
  1098.  
  1099.     long newlen= pr - aSeq->fBases;
  1100.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen+1);
  1101.     aSeq->fBases[newlen]= 0;
  1102.     aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen+1);
  1103.     aSeq->fMasks[newlen]= 0;
  1104.         
  1105.     aSeq->UpdateFlds();
  1106.     aSeq->Modified();
  1107.     return aSeq;
  1108. }
  1109.  
  1110.  
  1111.  
  1112. DSequence* DSequence::Translate(Boolean keepUnselected)
  1113. {    
  1114.     char  c;
  1115.     char    acodon[3];
  1116.     Boolean isrna, nocodon;
  1117.     char    *pr, *pc, *mr, *mc;
  1118.     long    len, fulllen, newlen, i, j, k;
  1119.     
  1120.     DSequence* aSeq= (DSequence*) Clone();        
  1121.     if (DCodons::NotAvailable()) return aSeq; // safer than returning NULL !?
  1122.     // !? what do we do w/ fMasks !?
  1123.     Boolean domask= (fMasks && fMasksOk);
  1124.     
  1125.     if (fSelStart < 0) fSelStart= 0;
  1126.     fulllen= this->fLength - fSelStart;
  1127.     len= fulllen;
  1128.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  1129.     
  1130.     switch (fKind) {
  1131.     
  1132.         case kRNA:
  1133.         case kDNA:
  1134.         case kNucleic: 
  1135.             {
  1136.             if (keepUnselected) {
  1137.                 pr= aSeq->fBases + fSelStart; // start at selection, leaving untranslated 5'
  1138.                 if (domask) mr= aSeq->fMasks + fSelStart;
  1139.                 }
  1140.             else {
  1141.                 pr= aSeq->fBases;
  1142.                  if (domask) mr= mr= aSeq->fMasks;
  1143.                  }
  1144.                  
  1145.             pc= this->fBases + fSelStart;
  1146.             if (domask) mc= this->fMasks + fSelStart;
  1147.             isrna= (fKind == kRNA);
  1148.             i= fSelStart;
  1149.             while (i < len) {
  1150.                 for (j=0; j<3; j++) {
  1151.                     c= toupper( *pc); pc++; // toupper is sometimes a MACRO ! no (*pc++) !
  1152.                     if (isrna && c=='U') c= 'T';
  1153.                     acodon[j]= c;
  1154.                     }
  1155.                 i += 3;
  1156.                 for (k= 0, nocodon= true; k<64; k++) 
  1157.                     if ( MemCmp(DCodons::codon(k),acodon,3) == 0) { 
  1158.                         *pr++= DCodons::amino(k); //gCodonTable[k].amino;
  1159.                         nocodon= false;
  1160.                         break;
  1161.                         }
  1162.                 if (nocodon) *pr++= '?';
  1163.                 if (domask) {
  1164.                     *mr++= *mc;
  1165.                     mc += 3;
  1166.                     }
  1167.                 }
  1168.                  // copy over untranslated portion
  1169.             if (keepUnselected) {
  1170.                 long savei= i;
  1171.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  1172.                 if (domask) for ( i= savei; i < fulllen; i++)  *mr++= *mc++; 
  1173.                 }
  1174.             }
  1175.             break;
  1176.             
  1177.         case kAmino: 
  1178.             {
  1179.             char *bestcodon;
  1180.             long  selend;
  1181.             
  1182.             if (len < fulllen) {
  1183.                 newlen= fulllen + len*3;
  1184.                 selend= fSelStart + len;
  1185.                 }
  1186.             else {
  1187.                 newlen= fulllen * 3;
  1188.                 selend= len;
  1189.                 }
  1190.             pc= this->fBases + fSelStart;
  1191.             aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  1192.             if (keepUnselected)
  1193.                 pr= aSeq->fBases + fSelStart;
  1194.             else
  1195.                 pr= aSeq->fBases;
  1196.                 
  1197.             if (domask) {
  1198.                 mc= this->fMasks + fSelStart;
  1199.                 aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  1200.                 if (keepUnselected)
  1201.                     mr= aSeq->fMasks + fSelStart;
  1202.                 else
  1203.                     mr= aSeq->fMasks;
  1204.                 }
  1205.                 
  1206.             for (i= fSelStart; i<selend; i++) {
  1207.                 c= toupper( *pc); pc++;// toupper is sometimes a MACRO ! no (*pc++) !
  1208.                 bestcodon= (char*) DCodons::FindBestCodon(c);
  1209.                 MemCpy( pr, bestcodon, 3);  
  1210.                 pr += 3;
  1211.                 if (domask) {
  1212.                     for (j=0; j<3; j++) *mr++= *mc;
  1213.                     mc++;
  1214.                     }
  1215.                 }
  1216.                  // copy over untranslated portion
  1217.             if (keepUnselected) {
  1218.                 long savei= i;
  1219.                 for ( ; i < fulllen; i++)  *pr++= *pc++; 
  1220.                 if (domask) for ( i=savei; i < fulllen; i++)  *mr++= *mc++; 
  1221.                 }
  1222.             }
  1223.             break;
  1224.         
  1225.         default:
  1226.             return NULL;
  1227.          
  1228.       }
  1229.         
  1230.     *pr= '\0';
  1231.     newlen= pr - aSeq->fBases;
  1232.     aSeq->fBases= (char*) MemMore( aSeq->fBases, newlen);
  1233.     if (domask) {
  1234.         *mr= '\0';
  1235.         newlen= mr - aSeq->fMasks;
  1236.         aSeq->fMasks= (char*) MemMore( aSeq->fMasks, newlen);
  1237.         }
  1238.     aSeq->UpdateFlds();
  1239.     aSeq->Modified();
  1240.     return aSeq;    
  1241. }
  1242.  
  1243.  
  1244. DSequence* DSequence::OnlyORF(char nonorf)
  1245. // convert sequence to ORF part only 
  1246. {
  1247.     DSequence* aSeq= (DSequence*) Clone();    
  1248.     
  1249.     if (fSelStart < 0) fSelStart= 0;
  1250.     long len= aSeq->fLength - fSelStart;
  1251.     if (fSelBases > 0 && fSelBases < len) len= fSelBases;
  1252.  
  1253.     long start = 0, fini= 0;
  1254.     long anchor= fSelStart;
  1255.     do {
  1256.         aSeq->SearchORF( start, fini);
  1257.         if (start != kSearchNotFound) {
  1258.             char* pr= aSeq->fBases + anchor;
  1259.             if (start>len) start= len;
  1260.             if (fini<start) fini= start+1;
  1261.             for ( ; anchor<start; anchor++) *pr++ = nonorf; 
  1262.             anchor= fini+1;
  1263.             fSelStart= anchor;
  1264.             }
  1265.     } while (start != kSearchNotFound);
  1266.         
  1267.     aSeq->UpdateFlds();
  1268.     aSeq->Modified();
  1269.     return aSeq;
  1270. }
  1271.  
  1272.  
  1273. void DSequence::SetORFmask(short masklevel, short frame)
  1274. {
  1275.     if (!fMasks || !fMasksOk) {
  1276.         FixMasks();
  1277.         if (!fMasks || !fMasksOk) return;
  1278.         }
  1279.         
  1280.     // revise this to do multiple frames in one go,
  1281.     //  offseting each anchor +1 beyond START of last orf, not after STOP
  1282.     // since separate frame calls return the same orfs !
  1283.     
  1284.     frame %= 3; // drop reverse frames
  1285.     long savesel= fSelStart;
  1286.     long savelen= fSelBases;
  1287.     fSelStart= frame;
  1288.     fSelBases= fLength - frame;
  1289.  
  1290.     long start = 0, fini= 0;
  1291.     long anchor= fSelStart;
  1292.     do {
  1293.         this->SearchORF( start, fini);
  1294.         if (start != kSearchNotFound) {
  1295.             long i;
  1296.             for (i= anchor; i<start; i++) SetMaskAt( i, masklevel, 0);
  1297.             for (i= start; i<=fini ; i++) SetMaskAt( i, masklevel, 1);
  1298.             if (fini == kSearchNotFound) {
  1299.                 start= kSearchNotFound;
  1300.                 }
  1301.             else {
  1302.               anchor= fini+1;
  1303.               fSelStart= anchor; // start+1 // !? want overlapped orfs !?
  1304.               }
  1305.             }
  1306.     } while (start != kSearchNotFound);
  1307.     
  1308.     fSelStart= savesel;
  1309.     fSelBases= savelen;
  1310. }
  1311.  
  1312. void DSequence::SetShowORF( short turnon) 
  1313.     fShowORF= turnon > 0; 
  1314.     if (turnon > 1) {
  1315.         if (turnon & 2) SetORFmask(5, 0);
  1316.         //if (turnon & 4) SetORFmask(6, 1);
  1317.         //if (turnon & 8) SetORFmask(7, 2);
  1318.         }
  1319. }
  1320.  
  1321. void DSequence::SetShowRE( short turnon) 
  1322. { fShowRE= turnon > 0; 
  1323. }
  1324.  
  1325. void DSequence::SetShowTrace( short turnon) 
  1326. { fShowTrace= turnon > 0; 
  1327. }
  1328.  
  1329.  
  1330. //Boolean domask= (fMasks && fMasksOk);
  1331.  
  1332.  
  1333. void DSequence::DoWrite(DFile* aFile, short format)
  1334. {  
  1335.     if (fLength>0) {
  1336.         DSeqFile::WriteSeqWrapper( aFile, fBases, fLength, format, fName);
  1337.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks) 
  1338.             DSeqFile::WriteMaskWrapper( aFile, fMasks, fLength, format, fName);
  1339.         }
  1340. }
  1341.  
  1342.  
  1343. void DSequence::DoWriteSelection(DFile* aFile, short format)
  1344. {
  1345.     if (fSelBases==0) 
  1346.         DoWrite( aFile, format);
  1347.     else if (fLength>0) {
  1348.         long aStart= Min( fSelStart, fLength);
  1349.         long aLength= Min( fSelBases, fLength - fSelStart);
  1350.         DSeqFile::WriteSeqWrapper(  aFile, fBases+aStart, aLength, format, fName);
  1351.         if (fMasks && fMasksOk && DSeqFile::gWriteMasks)  
  1352.             DSeqFile::WriteMaskWrapper( aFile, fMasks+aStart, aLength, format, fName);
  1353.         }
  1354. }
  1355.  
  1356.  
  1357.  
  1358.  
  1359. Boolean DSequence::GoodChar(char& aChar) 
  1360. {
  1361.     char* aacodes = gAminos;
  1362.     char* iupaccodes = gIubbase;
  1363.     char* nacodes = gPrimenuc;
  1364.     char    c;
  1365.     char* codes = NULL;
  1366.  
  1367.   if (aChar=='\n' || aChar=='\r')  
  1368.         return FALSE;
  1369.     else if (aChar<' ' || aChar>'~')  
  1370.         return TRUE; //allow return,tab,delete, ? option chars
  1371.  
  1372.   switch (fKind) {
  1373.       case kDNA            :
  1374.         case kRNA            : codes= nacodes; break;
  1375.         case kNucleic    : codes= iupaccodes; break;
  1376.         case kAmino        : codes= aacodes; break;
  1377.         default:
  1378.       case kOtherSeq: return TRUE;
  1379.         }
  1380.         
  1381.   c= toupper(aChar);
  1382.     while (*codes) {
  1383.         if (c == *codes) {
  1384.           switch (fKind) {
  1385.                 case kDNA: if (c == 'U') {
  1386.                     if (aChar=='u') aChar= 't'; else aChar= 'T';
  1387.                     }
  1388.                 break;
  1389.                 case kRNA: if (c == 'T') {
  1390.                     if (aChar=='t') aChar= 'u'; else aChar= 'U';
  1391.                     }
  1392.                 break;
  1393.                 }
  1394.             return TRUE;
  1395.             }
  1396.         codes++;
  1397.         }
  1398.     return FALSE;
  1399. }
  1400.  
  1401.  
  1402. Boolean DSequence::IsConsensus()
  1403. {
  1404.     return (fName && StringCmp(fName,kConsensus)==0);
  1405. }
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411. long DSequence::SearchAgain() 
  1412. {
  1413.     return Search( "", FALSE);
  1414. }
  1415.  
  1416.  
  1417.  
  1418. void DSequence::SearchORF( long& start, long& stop) 
  1419. {
  1420.     char  startc[2];
  1421.     long  i, j, k;
  1422.     short    ns, aaMinORFsize;
  1423.     CodonStat  stops[10];
  1424.     
  1425.     start= kSearchNotFound;
  1426.     stop = kSearchNotFound;
  1427.     if (DCodons::NotAvailable()) return;
  1428.     
  1429.     for (ns= 0, i= 0; i<64; i++) {
  1430.         if (ns<10 && DCodons::amino(i) == '*') 
  1431.             stops[ns++] = DCodons::fCodons[i];
  1432.         }
  1433.     if (ns == 0) return;
  1434.         
  1435.     switch (fKind) {  
  1436.         case kRNA:
  1437.         case kDNA:
  1438.         case kNucleic: 
  1439.              start= Search( DCodons::startcodon(), FALSE);
  1440.              if (start == kSearchNotFound) return;
  1441.              for (j= start+3; j<fLength; j += 3) {
  1442.                if ( j+3 - start >= DSeqList::gMinORFsize) 
  1443.                    for (k=0; k<ns; k++) {
  1444. #if 1
  1445.                        short jc, jt;
  1446.                        for (jc= 0, jt=0; jc<3; ) {
  1447.                            long tbit= NucleicBits( fBases[j+jt]);
  1448.                       long sbit= NucleicBits( stops[k].codon[jc]); 
  1449.                       if (tbit == kMaskIndel) jt++;
  1450.                         else if (!(kMaskNucs & tbit & sbit)) goto nextcodon;
  1451.                         else { jt++; jc++; }
  1452.                         }
  1453.                     stop= j+3; 
  1454.                     return;
  1455. #else                    
  1456.                      if (StrNICmp( fBases+j, stops[k].codon, 3) == 0) {
  1457.                          stop= j+3;
  1458.                          return;
  1459.                          }
  1460. #endif                
  1461.          nextcodon:
  1462.                      continue;
  1463.                      }
  1464.                  }
  1465.             break;
  1466.             
  1467.         case kAmino:
  1468.             startc[0]= DCodons::startamino();
  1469.             startc[1]= 0;
  1470.              aaMinORFsize= (DSeqList::gMinORFsize+2) / 3;
  1471.              start= Search( startc, FALSE);
  1472.              if (start == kSearchNotFound) return;
  1473.              for (j= start+1; j<fLength; j++) {
  1474.                if ( j - start >= aaMinORFsize) 
  1475.                   for (k=0; k<ns; k++) {
  1476.                      if (toupper(fBases[j]) == toupper(stops[k].amino)) {
  1477.                          stop= j+1; // +1 to include this codon
  1478.                          return;
  1479.                          }
  1480.                      }
  1481.                  }
  1482.             break;
  1483.             
  1484.         default:
  1485.             break;
  1486.         }
  1487. }
  1488.  
  1489.  
  1490.  
  1491.  
  1492. void DSequence::NucleicSearch(char* source, char* target, SearchRec& aSearchRec)
  1493. {
  1494.     long k, j, tBits, lens, ti;
  1495.     Boolean done;
  1496.  
  1497.                     //find target[ti] where tBits == kMaskA,C,G,T for fastest search
  1498.                     //This part is wasted time for SearchAgain... store tBits/ti in saverec...
  1499.     lens= StrLen(target);
  1500.     for (j= 0, ti= 0, tBits= 0; j<lens && !tBits; j++) {
  1501.         ti= j;
  1502.         tBits= NucleicBits( target[ti]);
  1503.         tBits &= kMaskNucs;  //drop RNA bit
  1504.         }
  1505.  
  1506.     do {
  1507. reloop:
  1508.             aSearchRec.indx += aSearchRec.step; 
  1509.             aSearchRec.lim  -= aSearchRec.step;    
  1510.             
  1511.             if (aSearchRec.step>0) {
  1512.                 for (j= 0; j<aSearchRec.lim; j++)
  1513.                  // if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx]))) 
  1514.                  if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1515.                  {
  1516.                     k= j; 
  1517.                     goto nextindx;
  1518.                  }
  1519.                 k= aSearchRec.lim;
  1520.                 }            
  1521.             else {  //step<0 IS BAD .. see UTextDoc version...
  1522.                 for (j= 0; j > -aSearchRec.lim; j--) 
  1523.                   //if (IsNucleicMatch( tBits, NucleicBits( source[j+aSearchRec.indx])))
  1524.                   if ( tBits & NucleicBits( source[j+aSearchRec.indx]) ) 
  1525.                 {
  1526.                     k= j; 
  1527.                     goto nextindx;
  1528.                     }
  1529.                 k= -aSearchRec.lim;
  1530.                 }
  1531.                 
  1532. nextindx:  
  1533.             aSearchRec.indx += k; 
  1534.             aSearchRec.lim  -= k;
  1535.                 //? not enough source left to match full target 
  1536.             if (aSearchRec.step>0) {
  1537.                 if (aSearchRec.lim < lens-ti) aSearchRec.lim= 0;
  1538.                 }            
  1539.             else {
  1540.                 if (aSearchRec.lim < ti) aSearchRec.lim= 0; //? or lim < ti-1 
  1541.                 }
  1542.             done= (aSearchRec.lim==0);
  1543.             
  1544.             if (!done) {
  1545.                 long srcstart= aSearchRec.indx - ti;
  1546.                 long js, jt;
  1547.                 for (js= 0, jt= 0; jt<lens; ) {
  1548. #if 1
  1549.                   long tbit= NucleicBits( target[jt]);
  1550.                   long sbit= NucleicBits( source[js+srcstart]); 
  1551.                   if (tbit == kMaskIndel) jt++;
  1552.                   else if (sbit == kMaskIndel) js++;
  1553.                     else if (!(kMaskNucs & tbit & sbit)) goto reloop;
  1554.                     else { jt++; js++; }
  1555. #else 
  1556.                   if (!(kMaskNucs & NucleicBits( target[jt]) & NucleicBits( source[js+srcstart]))) 
  1557.                       goto reloop;
  1558.                     else { jt++; js++; }
  1559. #endif
  1560.                     }
  1561.                 done= true;
  1562.                 }
  1563.         } while (!done);
  1564. }  
  1565.     
  1566.  
  1567. void DSequence::ProteinSearch(char* source, char* target, SearchRec& aSearchRec)
  1568. {
  1569.     //just toupper match of chars 
  1570.     char      tChar; 
  1571.     Boolean  done;
  1572.     long        lens, k, j;
  1573.  
  1574.     lens= StrLen( target);
  1575.     tChar= toupper( target[0]);
  1576.     
  1577.     do {
  1578. reloop:
  1579.             aSearchRec.indx += aSearchRec.step; 
  1580.             aSearchRec.lim  -= aSearchRec.step;    
  1581.             
  1582.             if (aSearchRec.step>0) {
  1583.                 for (j= 0; j<aSearchRec.lim; j++) 
  1584.                  if (tChar == toupper( source[j+aSearchRec.indx])) {
  1585.                     k= j;
  1586.                     goto nextindx;
  1587.                     }
  1588.                 k= aSearchRec.lim;
  1589.                 }            
  1590.             else {
  1591.                 for (j= 0; j > -aSearchRec.lim; j--)
  1592.                  if (tChar == toupper(source[j+aSearchRec.indx])) {
  1593.                     k= j; 
  1594.                     goto nextindx;
  1595.                     }
  1596.                 k= -aSearchRec.lim;
  1597.                 }
  1598.                 
  1599. nextindx:  
  1600.             aSearchRec.indx += k; 
  1601.             aSearchRec.lim  -= k;
  1602.                 //? not enough source left to match full target 
  1603.             if (aSearchRec.step>0) {
  1604.                 if (aSearchRec.lim < lens-1) aSearchRec.lim= 0;
  1605.                 }            
  1606.             else {
  1607.                 if (aSearchRec.lim < 1) aSearchRec.lim= 0;  
  1608.                 }
  1609.             done= (aSearchRec.lim==0);
  1610.             
  1611.             if (!done) {
  1612.                 for (j= 1; j<lens; j++) {
  1613.                     if (toupper( target[j]) != toupper( source[j+aSearchRec.indx])) 
  1614.                         goto reloop;
  1615.                     }
  1616.                 done= true;
  1617.                 }
  1618.         } while (!done);
  1619. }  
  1620.  
  1621.  
  1622.     
  1623.  
  1624. long DSequence::Search( char* target, Boolean backwards)
  1625. /* search for target in sequence;
  1626.     search == abs index into fBases[0..fLength] or kSearchNotFound
  1627.   if (target='') then find next  
  1628.   if (backwards) then backwards search
  1629. */
  1630. {
  1631.     long        limit, aStart;
  1632.     SearchRec  aSearchRec;
  1633.  
  1634.     aStart= fSelStart;
  1635.     if (!target || !*target) {  //search again
  1636.         if (fSearchRec.targ && (fSearchRec.step == -1 || fSearchRec.step == 1)) {  
  1637.             aSearchRec= fSearchRec;
  1638.             target= aSearchRec.targ;
  1639.             }        
  1640.         else {
  1641.             return kSearchNotFound;
  1642.             }
  1643.         }        
  1644.     else {
  1645.         limit= fLength; //StrLen(fBases);
  1646.         if (aStart < 0) aStart= 0;
  1647.         if (backwards) {
  1648.             if (!aStart) aStart= limit-1;
  1649.             else limit= aStart+1;  //? off-by-one ??
  1650.             }        
  1651.         else {
  1652.             if (aStart > limit) aStart= 0; 
  1653.             else limit -= aStart;
  1654.             }
  1655.         if (fSelBases > 0 && fSelBases < limit) limit= fSelBases;
  1656.         if (backwards) aSearchRec.step= -1;
  1657.         else aSearchRec.step= 1;
  1658.         aSearchRec.indx= aStart - aSearchRec.step;  //indx always in [0..handsize-1], except 1st is -1 
  1659.         aSearchRec.lim = limit + aSearchRec.step;  //lim always in [1..handsize] or 0=done, except 1st is hand+1 
  1660.         aSearchRec.targ= StrDup(target);
  1661.         }
  1662.  
  1663.     switch (fKind) {  
  1664.         case kRNA:
  1665.         case kDNA:
  1666.         case kNucleic: 
  1667.             NucleicSearch(fBases,target,aSearchRec); 
  1668.             break;
  1669.         default:
  1670.             ProteinSearch(fBases,target,aSearchRec);
  1671.             break;
  1672.         }
  1673.     
  1674.     fSearchRec= aSearchRec;
  1675.     if (aSearchRec.lim == 0) return kSearchNotFound;
  1676.     else return aSearchRec.indx;
  1677. }  
  1678.  
  1679.  
  1680.